// 基本数据类型
// 布尔值
var isBool = false; // 使用字面量创建，类型指定为boolean
// boolean是基本数据类型，Boolean是构造函数，实例化出的对象是Boolean类型
var createBoolean = new Boolean(1);
// 但是可以使用Boolean直接来创建一个boolean类型
var isBoolean = Boolean(false);
console.log(isBool, createBoolean, isBoolean);
// 数字
// number为数据类型，Number是其包装类型
var isNumber = 10;
isNumber = 10; // 二进制，结果为10
isNumber = 484; // 八进制，结果为484
isNumber = Infinity; // 无穷值，有正负
isNumber = NaN; // 非数字，isNaN()
// 字符串
// string为数据类型，String是其包装类型
var isStr = 'hello';
isStr = "hi ".concat(isStr); // 模板字符串
console.log(isStr); // hi hello
// 空值
// JavaScript中没有空值的概念，但是typescript中
// 可使用void表示没有任何返回值的函
function voidFuc() { }
// 也可以用于声明变量，但是声明的空值变量，只能赋值为undefined或者null，前提是strictNullChecks为指定或者设置为false
var isVoid = undefined;
// null和undefined是所有类型的子类型，被定义为null或undefined的变量，可以赋值给其他类型
var isNull = null;
// let num: number = undefined; // 前提是strictNullChecks为指定或者设置为false
// let num:number = void; // void不能赋值给除undefined和null外的类型
/******************************************* */
// 任意值
// 一般来说，定义变量并指定类型后，在后续的使用过程中不能赋值为其他类型的值
// isStr = 10; // 编译出错，isStr在定义时被指定为string，不能在使用的过程中赋值为number类型
// 如果定义为any任意值类型，那么在使用时也可以更改类型。任意值就表示可以是任意类型，不建议大量使用any，这将失去ts的特性
var isAny = 10;
isAny = 'hello';
// 既然任意值是可以为任意类型，那么也就可以调用任意方法，当然这些方法是有意义的
// 如果在声明变量时，未指明类型，则默认未any类型
var anyThing; // 类型为any
// 类型推论
// 在定义变量时，虽然未指定类型，但是ts可通过初始值的类型推论出变量的类型
var num2 = 10;
// num2 = 'hello'; // num2推论出类型为number，赋值为string类型时会编译出错
// 如果定义变量时，未指定类型，也没有初始值，那么其类型将会被推论为any
/******************************************* */
// 联合类型
// 表示值的类型可以是多种类型中的一种，联合类型采用|分割不同的类型
var strAndNum;
strAndNum = 1;
strAndNum = 'hello';
// strAndNum = undefined; // 前提是strictNullChecks为指定或者设置为false
// strAndNum = false; // strAndNum可为string、number类型中的一种，但是不能为其他的
// 只能访问联合类型的所有类型中共有的属性和方法，因为不确定具体的类型
strAndNum.split(','); // 可能会报错，如果根据类型推论能得到strAndNum的类型为string则编译正常，否则会报错
var student = {
    name: '张三',
    age: 18
};
var student2 = {
    name: '张三'
};
// 可选属性的意思是可以不存在该属性，但是如果出现了未在接口中定义的属性，那也是不行的。例如
var student3 = {
    name: '张三'
};
var student4 = {
    name: '张三',
    sex: 'man'
};
var student5 = {
    name: '张三',
    sex: 'man',
    id: 9527
};
// student5.id = 1234; // 无法修改只读属性
/******************************************* */
// 数组的类型
// 对象的类型我们一般采用接口的方式，数组的类型则比较灵活
// 使用类型+[]表示数组
var isNumberArr = [1, 2, 3];
// let isNumberArr: number[] = [1,2,'3']; // 数组中一般是单类型数据，不允许出现其他类型的数据
// 数组泛型，泛型中指定类型
var isArr = [1, 2, 3];
var isNumArr = [1, 2, 3];
function sum(x, y) {
    var args = arguments;
    console.log(arguments, args[0]);
}
sum(1, 2);
// 数组中一般是单类型数据，如果我们需要在数组中存在不同的数据类型，那么可以考虑任意类型数组
var isAnyArr = [1, '2', true];
/******************************************* */
// 函数的类型
// 函数定义的方式有两种：使用function声明或者采用函数表达式。如果需要使用ts对函数进行约束，那么其输入和输出都应该考虑到。
function sum1(x, y) {
    return x + y;
} // function
var sum2 = function (x, y) {
    return x + y;
}; // 表达式
var sum3 = function (x, y) {
    return x + y;
};
// 可选参数
// 类似于对象的可选属性，使用?来声明，值得注意的是可选参数后面不能再出现必需参数，并且可选参数在必需参数后面
function sum4(x, y, z) {
    if (z) {
        return x + y + z;
    }
    return x + y;
}
// 默认参数
// 可以给函数的参数添加默认值，ts会将添加了默认值的参数识别为可选参数，此时默认参数并没有位置要求，其后也可以跟必需参数
function sum5(x, y, z) {
    if (x === void 0) { x = 10; }
    if (z) {
        return x + y + z;
    }
    return x + y;
}
// 剩余参数
// 有时候参数很多，或者不确定有哪些参数，可以采用剩余参数的方式将这些参数都放在一个参数列表中
function sum6(x) {
    var items = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        items[_i - 1] = arguments[_i];
    }
    items.forEach(function (element) {
        x += element;
    });
    return x;
}
console.log(sum6(1, 2, 3, 4, 5)); // 15
function add(x, y) {
    if (isNaN(Number(x)) || isNaN(Number(y))) {
        return 0;
    }
    return Number(x) + Number(y);
}
console.log('add', add('1', 2));
